package com.xiaoxi.bms.common.filter;

import com.xiaoxi.bms.common.constant.constant.CommonConstants;
import com.xiaoxi.bms.common.constant.enumeration.statuscode.user.ValidateCodeUserEnums;
import com.xiaoxi.bms.common.exception.BMSSecurityException;
import com.xiaoxi.bms.common.util.RedisUtils;
import com.xiaoxi.bms.domain.common.ImageCode;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.annotation.Resource;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.time.LocalDateTime;
import java.util.Objects;

/**
 * @Author xiaoxi
 * @ProjectName bms
 * @PackageName com.xiaoxi.bms.common.filter
 * @ClassName ValidateCodeFilter
 * @Description TODO
 * @Date 2023/6/5 14:01
 * @Version 1.0
 */
@Component
@Slf4j
public class ValidateCodeFilter extends OncePerRequestFilter {

    @Resource
    private AuthenticationFailureHandler authenticationFailureHandler;

    @Resource
    private RedisUtils redisUtils;

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {

        try {
            // 登陆的时候 校验 验证码
            if (StringUtils.equals("/bms/user/api/v1/login", request.getRequestURI())) {
                log.info("uuid is : {}", request.getHeader("verificationCodeId"));
                checkVerificationCode(request);
            }
        } catch (BMSSecurityException e) {
            authenticationFailureHandler.onAuthenticationFailure(request, response, e);
            return;
        }
        filterChain.doFilter(request, response);

    }

    /**
     * 登陆的时候 校验 是否正确验证码
     *
     * @param request 请求
     */
    private void checkVerificationCode(HttpServletRequest request) {

        // uuid
        String verificationCodeId = request.getHeader("verificationCodeId");
        // 从请求中取出之前存入redis的验证码
        ImageCode codeInRedis = (ImageCode) redisUtils.get(CommonConstants.IMAGE_CODE + verificationCodeId);

        // 用户提供的验证码
        String codeInRequest = request.getHeader("verificationCode");

        // 用户提供验证码为空
        if (StringUtils.isEmpty(codeInRequest)) {
            throw new BMSSecurityException(ValidateCodeUserEnums.THE_VERIFICATION_CODE_CANNOT_BE_EMPTY);
        }

        // 系统验证码 无效
        if (Objects.isNull(codeInRedis)) {
            throw new BMSSecurityException(ValidateCodeUserEnums.THE_VERIFICATION_CODE_IS_INVALID);
        }

        // 系统验证码过期
        if (LocalDateTime.now().isAfter(codeInRedis.getExpireTime())) {
            throw new BMSSecurityException(ValidateCodeUserEnums.THE_VERIFICATION_CODE_HAS_EXPIRED);
        }

        // 验证码不匹配
        if (!StringUtils.equals(codeInRedis.getCode(), codeInRequest)) {
            redisUtils.remove(verificationCodeId);
            throw new BMSSecurityException(ValidateCodeUserEnums.VERIFICATION_CODES_DO_NOT_MATCH);
        }

        redisUtils.remove(verificationCodeId);

    }

}
